# 函数
# 代码的一个抽象

# 有三个半径
r1 = 1
r2 = 2.5
r3 = 3.6
# 计算三个圆的面积
p1 = 3.14 * r1 * r1
p2 = 3.14 * r2 * r2
p3 = 3.14 * r3 * r3
print(p1, p2, p3)


# 将代码进行抽象
# 定义一个函数 area_of_cycle
def area_of_cycle(r):
    pi = 3.1415926535
    print(pi * r * r)


area_of_cycle(r1)
area_of_cycle(r2)
area_of_cycle(r3)


# 计算1~100的和
# 1+2+3+4+......+100
# 100+99+98+......+1

# 计算1~n的和
def sum_1_to_n(n):
    sum = 0
    cnt = 1
    while cnt <= n:
        sum += cnt
        cnt += 1
    print(sum)


sum_1_to_n(10)
sum_1_to_n(100)


# 计算n的阶乘
# 用while循环实现
def jieCheng(n):
    res = 1
    while n >= 1:
        res *= n
        n -= 1
    print(res)


jieCheng(4)


# 用递归实现
# 递归函数需要满足两个条件：
# 1、有结束条件
# 2、自己调用自己

# 一般不推荐使用
# 每次递归都需要保留函数的状态 需要额外的资源
def recursion(n):
    if n == 1:
        return 1
    # 要计算n的阶乘 就相当于 n * (n-1)!
    return n * recursion(n - 1)


print(recursion(4))
'''
recursion(4) -> 4 * recursion(3)
                        3 * recursion(2)
                                2 * recursion(1)
                                        1
'''


# 函数的参数
# 计算x的2次方

# def power(x):
#     return x * x
#
#
# print(power(3))


# 计算x的3次方
# def power(x):
#     return x * x * x
#
#
# print(power(3))


# 计算x的n次方
# x 位置参数/必选参数
# n 默认参数 调用的时候如果不传则使用默认值
def power(x, n=2):
    return x ** n


print(power(2, 2))
print(power(2, 3))
print(power(2, 4))

print(power(3))
print(power(4))
print(power(5))


# 有几个数 1,2,3,4,5
# 计算这几个数的和

# 每一个数用一个参数接收
def sum_nums(a, b, c, d, e):
    print(a + b + c + d + e)


sum_nums(1, 2, 3, 4, 5)

# 如果有100个数 那是不是就要用100个参数接收呢？
# 用list将数存起来 然后传入函数 相当于只需要定义一个参数即可
list1 = [i for i in range(1, 101)]


def sum_nums_with_list(l):
    sum = 0
    for i in l:
        sum += i
    print(sum)


sum_nums_with_list(list1)


# 不管传入几个数 都会进行累加
# *args 在参数前加上*号 则表示可变参数
def sum_nums_with_args(*args):
    sum = 0
    for arg in args:
        sum += arg
    print(sum)


sum_nums_with_args(1)
sum_nums_with_args(1, 2)
sum_nums_with_args(1, 2, 3)
sum_nums_with_args(1, 2, 3, 4)

list2 = [1, 2, 3]
# 调用太麻烦
sum_nums_with_args(list2[0], list2[1], list2[2])
# 等价于
sum_nums_with_args(*list2)  # 可以简化调用


# 关键字参数
# 相对于可变参数来说 区别就是可以获取传入的参数的名称
def register(name, age, address, phone, **kw):
    dict1 = {
        "name": name,
        "age": age,
        "address": address,
        "phone": phone,
        "other": kw
    }
    print(dict1)


register("zhangsan", 18, "蜀山区", "188")
# 在调用时，会将 参数的名称 作为 key ，参数的值作为value 构建kw字典
register("zhangsan", 18, "蜀山区", "188", year="2000")
register("zhangsan", 18, "蜀山区", "188", year="2000", month="03")


# 命名关键字参数

# 检查传入的参数是否有 year、month

def register2(name, age, address, phone, **kw):
    if 'year' in kw.keys():
        print("year")
    if 'month' in kw.keys():
        print('month')
    dict1 = {
        "name": name,
        "age": age,
        "address": address,
        "phone": phone,
        "other": kw
    }
    print(dict1)


register2("zhangsan", 18, "蜀山区", "188")
register2("zhangsan", 18, "蜀山区", "188", year="2000")
register2("zhangsan", 18, "蜀山区", "188", year="2000", month="03")
register2("zhangsan", 18, "蜀山区", "188", year="2000", job='stu')


# 限定 传入的参数 必须有year，month
# 而且必须通过 year='2000', month='03'这种形式传进来
# year, month 命名关键字参数
def register3(name, age, address, phone, *, year, month):
    dict1 = {
        "name": name,
        "age": age,
        "address": address,
        "phone": phone,
        "year": year,
        "month": month
    }
    print(dict1)


register3("zhangsan", 18, "蜀山区", "188", year='2000', month='03')


def register4(name, age, address, phone, *args, year, month):
    print(args)
    dict1 = {
        "name": name,
        "age": age,
        "address": address,
        "phone": phone,
        "year": year,
        "month": month
    }
    print(dict1)


register4("zhangsan", 18, "蜀山区", "188", 1, 2, 3, 4, 5, year='2000', month='03')

# 匿名函数
# lambda表达式
list3 = [1, 2, 3, 4]


# 对list中的每一个元素做一个平方

def func(x):
    return x * x


print(list(map(func, list3)))

# 可以使用lambda表达式简化
f = lambda x: x * x

print(list(map(lambda x: x * x, list3)))
print(list(map(f, list3)))
